package com.example.canalclientsync.canal.handler;

import com.example.canalclientsync.mapstruct.DirMapping;
import com.example.canalclientsync.canal.mapper.db1.DirMapper;
import com.example.canalclientsync.canal.mapper.db1.ModelMapper;
import com.example.canalclientsync.canal.po.Dir;
import com.example.canalclientsync.canal.po.VirtualModel;
import com.example.canalclientsync.canal.service.ModelService;
import com.example.canalclientsync.es.document.EsModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * 文件夹创建、改名、移动、删除
 *
 * @author chen.cr
 * @since 2023/9/14
 */
@Component
@Slf4j
public class DirHandler implements EntryHandler<Dir> {

    @Resource
    private ElasticsearchRestTemplate elasticsearchTemplate;
    @Resource
    private ModelMapper modelMapper;
    @Resource
    private DirMapper dirMapper;
    @Resource
    private ModelService modelService;


    @Override
    public void insert(Dir dir) {
        log.info("[INSERT] >>>>>>>>>> dir, dirId:{}", dir.getId());
        if (!isEligibleSync(dir)) {
            log.info("<<<<<< 类型不符，无需同步");
            return;
        }

        EsModel esModel = DirMapping.INSTANCE.dir2EsModel(dir);

        Dir parentDir = dirMapper.findByDirIdAndTenantId(dir.getParentId(), dir.getTenantId());
        esModel.setParentDir(parentDir);

        modelService.fillDataByClassification(esModel, parentDir);

        elasticsearchTemplate.save(esModel);
        log.info("<<<<<< ES保存Dir成功, dirId:{}", dir.getId());
    }

    @Override
    public void update(Dir before, Dir after) {
        log.info("[UPDATE] >>>>>>>>>> dir, dirId:{}", after.getId());
        if (!isEligibleSync(after)) {
            log.info("<<<<<< 类型不符，无需同步");
            return;
        }

        EsModel esModel = DirMapping.INSTANCE.dir2EsModel(after);

        Dir parentDir = dirMapper.findByDirIdAndTenantId(after.getParentId(), after.getTenantId());
        esModel.setParentDir(parentDir);

        modelService.fillDataByClassification(esModel, parentDir);

        elasticsearchTemplate.save(esModel);
        log.info("更新文件夹成功");

        // 更新文件夹内的模型数据
        this.updateModelInDir(after);
        log.info("<<<<<< ES更新Dir成功, dirId:{}", after.getId());
    }


    @Override
    public void delete(Dir dir) {
        log.info("[DELETE] >>>>>>>>> dir, dirId:{}", dir.getId());
        if (!isEligibleSync(dir)) {
            log.info("<<<<<< 类型不符，无需同步");
            return;
        }
        elasticsearchTemplate.delete(dir.getId().toString(), EsModel.class);
        log.info("<<<<<< ES删除Dir成功");
    }



    private boolean isEligibleSync(Dir dir) {
        // 只有三种文件目前能被同步过去
        // PROJECT_DIR(15, "项目空间的普通文件夹", 15),
        // PERSONAL_DIR(10, "个人空间的普通文件夹", 10),
        // DEPARTMENT_DIR(12, "部门空间的普通文件夹", 12),
        return dir.getType() == 10 || dir.getType() == 12 || dir.getType() == 15;
    }


    /**
     * 同步更新当前文件夹下的文件模型数据
     *
     * @param after
     */
    private void updateModelInDir(Dir after) {
        List<VirtualModel> modelsInDir = modelMapper.findByDirIdAndTenantId(after.getId(), after.getTenantId());
        log.info("需要同步更新文件夹内的模型共{}个", modelsInDir.size());
        if (!CollectionUtils.isEmpty(modelsInDir)) {
            for (VirtualModel model : modelsInDir) {
                // 重新构建，更新模型数据
                EsModel esModel = modelService.buildFromVirtualModel(model, after);
                if (esModel == null) {
                    continue;
                }
                elasticsearchTemplate.save(esModel);
            }
        }
        log.info("Es更新文件夹内的模型数据完成");
    }

}
